//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V0.1.2
#include "exti_bsp.h"

/*EXTI总管理结构体*/
static struct
{
	volatile unsigned int exti_line_mutex;                    //外部中断线互斥锁
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin0;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin1;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin2;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin3;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin4;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin5;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin6;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin7;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin8;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin9;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin10;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin11;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin12;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin13;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin14;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Pin15;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_PVD;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_RTC;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_USB;
	WHT_EXTI_BSP_Interrupt_Callback_t interrupt_callback_Ethernet;
}EXTI_Data = { 0 };


/*EXTI中断优先级配置*/
static void EXTI_NVIC_Config(unsigned char NVIC_IRQChannel)
{
    NVIC_InitTypeDef NVIC_InitStruct;

    /* 嵌套向量中断控制器组选择 */
    //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

    /* 配置中断源 */
    NVIC_InitStruct.NVIC_IRQChannel = NVIC_IRQChannel;
    /* 抢断优先级*/
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 15;
    /* 子优先级 */
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    /* 使能中断 */
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    /* 初始化配置NVIC */
    NVIC_Init(&NVIC_InitStruct);
}
/*EXTI GPIO中断的GPIO初始化*/
static void WHT_EXTI_BSP_GPIO_Init(const WHT_EXTI_Config_t* config)
{
	WHT_GPIO_Port_enum Portx;

	switch (config->GPIO_Port_Source)
	{
	case Exti_Source_GPIOA:Portx = PortA; break;
	case Exti_Source_GPIOB:Portx = PortB; break;
	case Exti_Source_GPIOC:Portx = PortC; break;
	case Exti_Source_GPIOD:Portx = PortD; break;
	case Exti_Source_GPIOE:Portx = PortE; break;
	case Exti_Source_GPIOF:Portx = PortF; break;
	case Exti_Source_GPIOG:Portx = PortG; break;
	default:
		return;
	}
	WHT_GPIO_BSP.WHT_Set_Clock(Portx, ENABLE);
	WHT_GPIO_BSP.WHT_Set_Pin(Portx, Pin0 << config->GPIO_Pin_Source, Hig);
	WHT_GPIO_BSP.WHT_Set_Mode(Portx, Pin0 << config->GPIO_Pin_Source, Mode_IN_FLOATING);
}
/*EXTI配置*/
static void WHT_EXTI_BSP_Config(const WHT_EXTI_Config_t* config)
{
	WHT_EXTI_BSP_Interrupt_Callback_t* Interrupt_Callback;
	EXTI_InitTypeDef EXTI_InitStruct;
	unsigned char NVIC_IRQChannel;

	switch (config->Line)
	{
	case Exti_Line_Pin0:
		NVIC_IRQChannel = EXTI0_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin0;
		break;
	case Exti_Line_Pin1:
		NVIC_IRQChannel = EXTI1_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin1;
		break;
	case Exti_Line_Pin2:
		NVIC_IRQChannel = EXTI2_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin2;
		break;
	case Exti_Line_Pin3:
		NVIC_IRQChannel = EXTI3_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin3;
		break;
	case Exti_Line_Pin4:
		NVIC_IRQChannel = EXTI4_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin4;
		break;
	case Exti_Line_Pin5:
		NVIC_IRQChannel = EXTI9_5_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin5;
		break;
	case Exti_Line_Pin6:
		NVIC_IRQChannel = EXTI9_5_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin6;
		break;
	case Exti_Line_Pin7:
		NVIC_IRQChannel = EXTI9_5_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin7;
		break;
	case Exti_Line_Pin8:
		NVIC_IRQChannel = EXTI9_5_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin8;
		break;
	case Exti_Line_Pin9:
		NVIC_IRQChannel = EXTI9_5_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin9;
		break;
	case Exti_Line_Pin10:
		NVIC_IRQChannel = EXTI15_10_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin10;
		break;
	case Exti_Line_Pin11:
		NVIC_IRQChannel = EXTI15_10_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin11;
		break;
	case Exti_Line_Pin12:
		NVIC_IRQChannel = EXTI15_10_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin12;
		break;
	case Exti_Line_Pin13:
		NVIC_IRQChannel = EXTI15_10_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin13;
		break;
	case Exti_Line_Pin14:
		NVIC_IRQChannel = EXTI15_10_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin14;
		break;
	case Exti_Line_Pin15:
		NVIC_IRQChannel = EXTI15_10_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Pin15;
		break;
	case Exti_Line_PVD:
		NVIC_IRQChannel = PVD_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_PVD;
		break;
	case Exti_Line_RTC:
		NVIC_IRQChannel = RTCAlarm_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_RTC;
		break;
	case Exti_Line_USB:
		NVIC_IRQChannel = USBWakeUp_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_USB;
		break;
	case Exti_Line_Ethernet:
		//NVIC_IRQChannel = ETH_WKUP_IRQn;
		Interrupt_Callback = &EXTI_Data.interrupt_callback_Ethernet;
		return;//STM32F103 no eth
	default:
		return;
	}
	if (config->Name == Exti_GPIO)
	{
		WHT_EXTI_BSP_GPIO_Init(config);
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
		GPIO_EXTILineConfig(config->GPIO_Port_Source, config->GPIO_Pin_Source);//配置相应信号源
	}
	if (config->Mode == Mode_Interrupt)
	{
		EXTI_NVIC_Config(NVIC_IRQChannel);
		*Interrupt_Callback = config->Interrupt_Callback;
	}
	else
		*Interrupt_Callback = NULL;
	
	EXTI_InitStruct.EXTI_Line    = config->Line;
	EXTI_InitStruct.EXTI_Trigger = (EXTITrigger_TypeDef)config->Trigger;
	EXTI_InitStruct.EXTI_Mode    = (EXTIMode_TypeDef)config->Mode;
	EXTI_InitStruct.EXTI_LineCmd = ENABLE;//开启中断或事件
	EXTI_ClearFlag(config->Line);
	EXTI_Init(&EXTI_InitStruct);
}
/*EXTI线路使能或失能*/
static void WHT_EXTI_BSP_Line_Cmd(const WHT_EXTI_Config_t* config, FunctionalState state)
{
	EXTI_InitTypeDef EXTI_InitStruct;

	EXTI_InitStruct.EXTI_Line    = config->Line;
	EXTI_InitStruct.EXTI_Trigger = (EXTITrigger_TypeDef)config->Trigger;
	EXTI_InitStruct.EXTI_Mode    = (EXTIMode_TypeDef)config->Mode;
	EXTI_InitStruct.EXTI_LineCmd = state;//开启中断或事件
	EXTI_ClearFlag(config->Line);
	EXTI_Init(&EXTI_InitStruct);
}
/*EXTI手动触发中断或关闭中断*/
static void WHT_EXTI_BSP_Soft_Interrupt(const WHT_EXTI_Config_t* config, FunctionalState state)
{
	if (state == DISABLE)
		EXTI_ClearITPendingBit(config->Line);
	else
		EXTI_GenerateSWInterrupt(config->Line);
}
/*EXTI获取线路锁*/
static FlagStatus WHT_EXTI_BSP_Get_Line_Mutex_State(const WHT_EXTI_Config_t* config)
{
	return (EXTI_Data.exti_line_mutex & config->Line) == config->Line ? SET : RESET;
}
/*EXTI清除线路锁*/
static void WHT_EXTI_BSP_Clr_Line_Mutex_State(const WHT_EXTI_Config_t* config)
{
	EXTI_Data.exti_line_mutex &= ~config->Line;
}


/*EXTI注册API*/
void WHT_EXTI_BSP_Register(WHT_EXTI_Line_enum line, WHT_EXTI_BSP_t* bsp)
{
	bsp->WHT_Get_Line_Mutex_State = WHT_EXTI_BSP_Get_Line_Mutex_State;
	bsp->WHT_Clr_Line_Mutex_State = WHT_EXTI_BSP_Clr_Line_Mutex_State;
	if ((EXTI_Data.exti_line_mutex & line) == line)//此线路已经被注册上了
	{
		bsp->WHT_Config         = NULL;
		bsp->WHT_Line_Cmd       = NULL;
		bsp->WHT_Soft_Interrupt = NULL;
	}
	else
	{
		EXTI_Data.exti_line_mutex |= line;//注册到此线路
		bsp->WHT_Config         = WHT_EXTI_BSP_Config;
		bsp->WHT_Line_Cmd       = WHT_EXTI_BSP_Line_Cmd;
		bsp->WHT_Soft_Interrupt = WHT_EXTI_BSP_Soft_Interrupt;
	}
}


/*EXTI0中断服务程序*/
void EXTI0_IRQHandler(void)
{
	if (EXTI_GetITStatus(Exti_Line_Pin0) == SET)
	{
		if (EXTI_Data.interrupt_callback_Pin0 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin0();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin0);
	}
}
/*EXTI1中断服务程序*/
void EXTI1_IRQHandler(void)
{
	if (EXTI_GetITStatus(Exti_Line_Pin1) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin1 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin1();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin1);
	}
}
/*EXTI2中断服务程序*/
void EXTI2_IRQHandler(void)
{
	if (EXTI_GetITStatus(Exti_Line_Pin2) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin2 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin2();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin2);
	}
}
/*EXTI3中断服务程序*/
void EXTI3_IRQHandler(void)
{
	if (EXTI_GetITStatus(Exti_Line_Pin3) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin3 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin3();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin3);
	}
}
/*EXTI4中断服务程序*/
void EXTI4_IRQHandler(void)
{
	if (EXTI_GetITStatus(Exti_Line_Pin4) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin4 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin4();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin4);
	}
}
/*EXTI5 6 7 8 9中断服务程序*/
void EXTI9_5_IRQHandler(void)
{
	if (EXTI_GetITStatus(Exti_Line_Pin5) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin5 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin5();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin5);
	}
	else if (EXTI_GetITStatus(Exti_Line_Pin6) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin6 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin6();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin6);
	}
	else if (EXTI_GetITStatus(Exti_Line_Pin7) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin7 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin7();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin7);
	}
	else if (EXTI_GetITStatus(Exti_Line_Pin8) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin8 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin8();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin8);
	}
	else if (EXTI_GetITStatus(Exti_Line_Pin9) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin9 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin9();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin9);
	}
}
/*EXTI10 11 12 13 14 15中断服务程序*/
void EXTI15_10_IRQHandler(void)
{
	if (EXTI_GetITStatus(Exti_Line_Pin10) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin10 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin10();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin10);
	}
	else if (EXTI_GetITStatus(Exti_Line_Pin11) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin11 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin11();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin11);
	}
	else if (EXTI_GetITStatus(Exti_Line_Pin12) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin12 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin12();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin12);
	}
	else if (EXTI_GetITStatus(Exti_Line_Pin13) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin13 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin13();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin13);
	}
	else if (EXTI_GetITStatus(Exti_Line_Pin14) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin14 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin14();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin14);
	}
	else if (EXTI_GetITStatus(Exti_Line_Pin15) != RESET)
	{
		if (EXTI_Data.interrupt_callback_Pin15 != NULL)
		{
			EXTI_Data.interrupt_callback_Pin15();
		}
		EXTI_ClearITPendingBit(Exti_Line_Pin15);
	}
}
/*EXTI电源管理中断服务程序*/
void PVD_IRQHandler(void)
{
	if (EXTI_Data.interrupt_callback_PVD != NULL)
	{
		EXTI_Data.interrupt_callback_PVD();
	}
	EXTI_ClearITPendingBit(Exti_Line_PVD);
}
/*EXTI RTC闹钟中断服务程序*/
void RTCAlarm_IRQHandler(void)
{
	if (EXTI_Data.interrupt_callback_RTC != NULL)
	{
		EXTI_Data.interrupt_callback_RTC();
	}
	EXTI_ClearITPendingBit(Exti_Line_RTC);
}
/*EXTI USB唤醒中断服务程序*/
void USBWakeUp_IRQHandler(void)
{
	if (EXTI_Data.interrupt_callback_USB != NULL)
	{
		EXTI_Data.interrupt_callback_USB();
	}
	EXTI_ClearITPendingBit(Exti_Line_USB);
}
